-
Notifications
You must be signed in to change notification settings - Fork 457
perf: reduce calls to Path.resolve #14460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Bootstrap import analysisComparison of import times between this PR and base. SummaryThe average import time from this PR is: 237 ± 2 ms. The average import time from base is: 269 ± 3 ms. The import time difference between this PR and base is: -31.6 ± 0.1 ms. Import time breakdownThe following import paths have grown:
|
Performance SLOsComparing candidate prf/avoid-resolve-calls (d2db191) with baseline main (ba014c0) 📈 Performance Regressions (1 suite)📈 telemetryaddmetric - 30/30✅ 1-count-metric-1-timesTime: ✅ 3.194µs (SLO: <20.000µs 📉 -84.0%) vs baseline: +2.5% Memory: ✅ 32.126MB (SLO: <34.000MB -5.5%) vs baseline: +4.9% ✅ 1-count-metrics-100-timesTime: ✅ 212.493µs (SLO: <250.000µs 📉 -15.0%) vs baseline: +1.3% Memory: ✅ 32.224MB (SLO: <34.000MB -5.2%) vs baseline: +5.2% ✅ 1-distribution-metric-1-timesTime: ✅ 3.291µs (SLO: <20.000µs 📉 -83.5%) vs baseline: 📈 +12.6% Memory: ✅ 32.165MB (SLO: <34.000MB -5.4%) vs baseline: +5.0% ✅ 1-distribution-metrics-100-timesTime: ✅ 190.375µs (SLO: <220.000µs 📉 -13.5%) vs baseline: -0.2% Memory: ✅ 32.106MB (SLO: <34.000MB -5.6%) vs baseline: +5.0% ✅ 1-gauge-metric-1-timesTime: ✅ 2.095µs (SLO: <20.000µs 📉 -89.5%) vs baseline: +0.4% Memory: ✅ 32.086MB (SLO: <34.000MB -5.6%) vs baseline: +4.9% ✅ 1-gauge-metrics-100-timesTime: ✅ 124.150µs (SLO: <150.000µs 📉 -17.2%) vs baseline: -0.8% Memory: ✅ 32.047MB (SLO: <34.000MB -5.7%) vs baseline: +4.7% ✅ 1-rate-metric-1-timesTime: ✅ 3.112µs (SLO: <20.000µs 📉 -84.4%) vs baseline: -0.2% Memory: ✅ 32.204MB (SLO: <34.000MB -5.3%) vs baseline: +5.2% ✅ 1-rate-metrics-100-timesTime: ✅ 215.580µs (SLO: <250.000µs 📉 -13.8%) vs baseline: +2.5% Memory: ✅ 32.027MB (SLO: <34.000MB -5.8%) vs baseline: +4.5% ✅ 100-count-metrics-100-timesTime: ✅ 21.379ms (SLO: <23.500ms -9.0%) vs baseline: +0.3% Memory: ✅ 32.126MB (SLO: <34.000MB -5.5%) vs baseline: +4.9% ✅ 100-distribution-metrics-100-timesTime: ✅ 2.015ms (SLO: <2.250ms 📉 -10.5%) vs baseline: +1.6% Memory: ✅ 32.067MB (SLO: <34.000MB -5.7%) vs baseline: +4.7% ✅ 100-gauge-metrics-100-timesTime: ✅ 1.285ms (SLO: <1.550ms 📉 -17.1%) vs baseline: +0.8% Memory: ✅ 32.204MB (SLO: <34.000MB -5.3%) vs baseline: +5.1% ✅ 100-rate-metrics-100-timesTime: ✅ 2.185ms (SLO: <2.550ms 📉 -14.3%) vs baseline: -0.5% Memory: ✅ 32.185MB (SLO: <34.000MB -5.3%) vs baseline: +5.4% ✅ flush-1-metricTime: ✅ 4.651µs (SLO: <20.000µs 📉 -76.7%) vs baseline: 📈 +11.7% Memory: ✅ 32.067MB (SLO: <34.000MB -5.7%) vs baseline: +4.3% ✅ flush-100-metricsTime: ✅ 180.641µs (SLO: <250.000µs 📉 -27.7%) vs baseline: -0.3% Memory: ✅ 32.027MB (SLO: <34.000MB -5.8%) vs baseline: +4.5% ✅ flush-1000-metricsTime: ✅ 2.204ms (SLO: <2.500ms 📉 -11.9%) vs baseline: +1.0% Memory: ✅ 32.991MB (SLO: <34.500MB -4.4%) vs baseline: +5.4% 🟡 Near SLO Breach (4 suites)🟡 djangosimple - 30/30✅ appsecTime: ✅ 20.512ms (SLO: <22.300ms -8.0%) vs baseline: -0.1% Memory: ✅ 65.431MB (SLO: <67.000MB -2.3%) vs baseline: +5.0% ✅ exception-replay-enabledTime: ✅ 1.349ms (SLO: <1.450ms -7.0%) vs baseline: -0.4% Memory: ✅ 64.518MB (SLO: <67.000MB -3.7%) vs baseline: +5.4% ✅ iastTime: ✅ 20.497ms (SLO: <22.250ms -7.9%) vs baseline: +0.2% Memory: ✅ 65.502MB (SLO: <67.000MB -2.2%) vs baseline: +5.3% ✅ profilerTime: ✅ 15.294ms (SLO: <16.550ms -7.6%) vs baseline: ~same Memory: ✅ 53.679MB (SLO: <54.500MB 🟡 -1.5%) vs baseline: +4.9% ✅ resource-renamingTime: ✅ 20.629ms (SLO: <21.750ms -5.2%) vs baseline: +0.6% Memory: ✅ 65.531MB (SLO: <67.000MB -2.2%) vs baseline: +5.2% ✅ span-code-originTime: ✅ 26.230ms (SLO: <28.200ms -7.0%) vs baseline: +0.3% Memory: ✅ 67.526MB (SLO: <69.500MB -2.8%) vs baseline: +5.0% ✅ tracerTime: ✅ 20.541ms (SLO: <21.750ms -5.6%) vs baseline: +0.2% Memory: ✅ 65.459MB (SLO: <67.000MB -2.3%) vs baseline: +5.1% ✅ tracer-and-profilerTime: ✅ 22.143ms (SLO: <23.500ms -5.8%) vs baseline: +0.3% Memory: ✅ 66.709MB (SLO: <67.500MB 🟡 -1.2%) vs baseline: +5.6% ✅ tracer-dont-create-db-spansTime: ✅ 19.390ms (SLO: <21.500ms -9.8%) vs baseline: -0.1% Memory: ✅ 65.462MB (SLO: <66.000MB 🟡 -0.8%) vs baseline: +5.1% ✅ tracer-minimalTime: ✅ 16.588ms (SLO: <17.500ms -5.2%) vs baseline: -0.3% Memory: ✅ 65.196MB (SLO: <66.000MB 🟡 -1.2%) vs baseline: +5.0% ✅ tracer-nativeTime: ✅ 20.496ms (SLO: <21.750ms -5.8%) vs baseline: ~same Memory: ✅ 71.452MB (SLO: <72.500MB 🟡 -1.4%) vs baseline: +5.4% ✅ tracer-no-cachesTime: ✅ 18.494ms (SLO: <19.650ms -5.9%) vs baseline: +0.1% Memory: ✅ 65.242MB (SLO: <67.000MB -2.6%) vs baseline: +4.8% ✅ tracer-no-databasesTime: ✅ 18.861ms (SLO: <20.100ms -6.2%) vs baseline: +0.7% Memory: ✅ 65.275MB (SLO: <67.000MB -2.6%) vs baseline: +5.4% ✅ tracer-no-middlewareTime: ✅ 20.156ms (SLO: <21.500ms -6.3%) vs baseline: -0.3% Memory: ✅ 65.448MB (SLO: <67.000MB -2.3%) vs baseline: +5.0% ✅ tracer-no-templatesTime: ✅ 20.326ms (SLO: <22.000ms -7.6%) vs baseline: +0.1% Memory: ✅ 65.450MB (SLO: <67.000MB -2.3%) vs baseline: +5.0% 🟡 errortrackingdjangosimple - 6/6✅ errortracking-enabled-allTime: ✅ 18.106ms (SLO: <19.850ms -8.8%) vs baseline: ~same Memory: ✅ 65.352MB (SLO: <66.500MB 🟡 -1.7%) vs baseline: +5.0% ✅ errortracking-enabled-userTime: ✅ 18.122ms (SLO: <19.400ms -6.6%) vs baseline: +0.3% Memory: ✅ 65.333MB (SLO: <66.500MB 🟡 -1.8%) vs baseline: +4.9% ✅ tracer-enabledTime: ✅ 18.065ms (SLO: <19.450ms -7.1%) vs baseline: -0.4% Memory: ✅ 65.294MB (SLO: <66.500MB 🟡 -1.8%) vs baseline: +5.1% 🟡 flasksqli - 6/6✅ appsec-enabledTime: ✅ 3.935ms (SLO: <4.200ms -6.3%) vs baseline: -0.2% Memory: ✅ 63.445MB (SLO: <66.000MB -3.9%) vs baseline: +5.2% ✅ iast-enabledTime: ✅ 2.460ms (SLO: <2.800ms 📉 -12.2%) vs baseline: +0.5% Memory: ✅ 59.022MB (SLO: <60.000MB 🟡 -1.6%) vs baseline: +5.1% ✅ tracer-enabledTime: ✅ 2.072ms (SLO: <2.250ms -7.9%) vs baseline: ~same Memory: ✅ 52.121MB (SLO: <54.500MB -4.4%) vs baseline: +5.0% 🟡 otelspan - 22/22✅ add-eventTime: ✅ 45.384ms (SLO: <47.150ms -3.7%) vs baseline: ~same Memory: ✅ 45.303MB (SLO: <47.000MB -3.6%) vs baseline: +5.2% ✅ add-metricsTime: ✅ 319.826ms (SLO: <344.800ms -7.2%) vs baseline: -0.2% Memory: ✅ 553.546MB (SLO: <562.000MB 🟡 -1.5%) vs baseline: +4.9% ✅ add-tagsTime: ✅ 293.387ms (SLO: <314.000ms -6.6%) vs baseline: +0.9% Memory: ✅ 555.360MB (SLO: <563.500MB 🟡 -1.4%) vs baseline: +5.0% ✅ get-contextTime: ✅ 82.738ms (SLO: <92.350ms 📉 -10.4%) vs baseline: ~same Memory: ✅ 40.223MB (SLO: <46.500MB 📉 -13.5%) vs baseline: +4.9% ✅ is-recordingTime: ✅ 42.961ms (SLO: <44.500ms -3.5%) vs baseline: ~same Memory: ✅ 44.645MB (SLO: <47.500MB -6.0%) vs baseline: +5.1% ✅ record-exceptionTime: ✅ 61.871ms (SLO: <67.650ms -8.5%) vs baseline: -0.2% Memory: ✅ 40.504MB (SLO: <47.000MB 📉 -13.8%) vs baseline: +4.8% ✅ set-statusTime: ✅ 48.688ms (SLO: <50.400ms -3.4%) vs baseline: -0.2% Memory: ✅ 44.593MB (SLO: <47.000MB -5.1%) vs baseline: +5.0% ✅ startTime: ✅ 42.218ms (SLO: <43.450ms -2.8%) vs baseline: ~same Memory: ✅ 44.610MB (SLO: <47.000MB -5.1%) vs baseline: +5.0% ✅ start-finishTime: ✅ 83.210ms (SLO: <88.000ms -5.4%) vs baseline: +0.1% Memory: ✅ 34.524MB (SLO: <46.500MB 📉 -25.8%) vs baseline: +4.7% ✅ start-finish-telemetryTime: ✅ 84.778ms (SLO: <89.000ms -4.7%) vs baseline: +0.3% Memory: ✅ 34.603MB (SLO: <46.500MB 📉 -25.6%) vs baseline: +5.0% ✅ update-nameTime: ✅ 44.253ms (SLO: <45.150ms 🟡 -2.0%) vs baseline: +0.7% Memory: ✅ 44.908MB (SLO: <47.000MB -4.5%) vs baseline: +5.2%
|
Calls to `Path.resolve` turn out to be quite expensive. We try to avoid them by checking whether a Path object actually needs to be resolved. In many cases, we just need to check whether the path is absolute or a link and then only resolve when necessary.
e11c736
to
b8b536d
Compare
b1305a8
to
6ce2a37
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worried about the caching of something that can technically change at runtime, but in general LGTM
Other than the profile, do we have any performance regression tests for this? In theory the serverless start up overhead ones should but that is fairly indirect regression test. |
We could add a microbenchmark of |
Calls to
Path.resolve
turn out to be quite expensive. We try to avoid them by checking whether a Path object actually needs to be resolved. In many cases, we just need to check whether the path is absolute or a link and then only resolve when necessary.Performance Analysis
We take Symbol DB as a part of the codebase that exercises the code of interest. The before flame graph shows the CPU cost of calls to
resolve
. The after flame graph shows how they can be avoided in many cases.Before
After
Checklist
Reviewer Checklist